using System;
using System.Xml;
using System.DirectoryServices;
using CDOEXM;
using ActiveDs;
using System.Collections;


namespace ADModify.Library
{
	/// <summary>
	/// Summary description for ImportMailboxRights.
	/// </summary>
	public class ImportMailboxRights
	{

		public void ParseXML(XmlWriter logWriter, bool CMDMode, bool MailboxRightsOverwrite)
		{

			LogFile log = new LogFile();
			XmlDocument docXml = new XmlDocument();
			docXml.Load("mbxrights.xml");
			XmlNodeList lstXml = docXml.GetElementsByTagName("MailboxRights");
		
			bool HaveDisplayedUserCount = false;
			int UserCount = lstXml[0].ChildNodes.Count;
			string UserDN = "";
			int ACEEntryCount;
			int CurrentUserCount = 0;  //used to track the # of the current user
			int dots = 0;


			//show the user count
			if(!HaveDisplayedUserCount && CMDMode)
			{
				
				Console.WriteLine("\nNumber of User modifications found for this this log file:  {0}", UserCount + "\n");
				
			}
			HaveDisplayedUserCount = true; //flip the bit so we only print this once to the console

			Console.WriteLine("");
			Console.WriteLine("0%                      50%                     100%");
			Console.WriteLine("|----|----|----|----|----|----|----|----|----|----|");
			Console.Write(".");
			dots++;

			//for progress bar
			float UserCountDivided = 50/(float)UserCount;	//this number remains constant
			float UserCountDividedTemp = UserCountDivided;		//this number we increment
			int UserCountDividedWhole = 0;
			float UserCountDividedDecimalCount = 0;
			float UserCountDividedDecimalCountConst = 0;
			string UserCountDividedDecimalCountString = null;
			string[] UserCountDividedString = UserCountDivided.ToString().Split('.');	//split at the decimal

			//calculate the whole and decimal increment counters
			UserCountDividedWhole = Convert.ToInt16(UserCountDividedString[0],10);	//grab the whole number on the left
			if(UserCountDividedString.GetUpperBound(0) == 1)
			{
				UserCountDividedDecimalCountString = UserCountDividedString[1].Replace(".", "");
				UserCountDividedDecimalCountString = "." + UserCountDividedDecimalCountString;
				UserCountDividedDecimalCount = float.Parse(UserCountDividedDecimalCountString);
			}
			else
			{
				UserCountDividedDecimalCount = 0;
			}
			UserCountDividedDecimalCountConst = UserCountDividedDecimalCount;


				for(int i=0;i<=UserCount-1;i++)
				{

					CurrentUserCount++;

					if(dots<=50)		//just to be safe, make sure we're under out dots quota so we don't
					{					//exceed the 100% mark
						for(int b=0; b<= UserCountDividedWhole-1; b++)
						{
							if(dots<=50)
							{
								Console.Write(".");
								dots++;
							}
						}
						if(UserCountDividedDecimalCount>=1)
						{
							if(dots<=50)
							{
								UserCountDividedDecimalCount--;
								Console.Write(".");
								dots++;
							}
						}
						UserCountDividedDecimalCount = UserCountDividedDecimalCount + UserCountDividedDecimalCountConst;
					}

					try
					{
						UserDN = lstXml[0].ChildNodes[i].Attributes["UserDN"].Value;
						ModifyAttributes admod = new ModifyAttributes();
										
						//It gets the users Mailbox Security Descriptor or else it gets the hose again
						DirectoryEntry ent = new DirectoryEntry(UserDN);
						IExchangeMailbox objUser = (IExchangeMailbox)ent.NativeObject;
						SecurityDescriptor sd = (SecurityDescriptor)objUser.MailboxRights;
						IADsAccessControlList dacl = (IADsAccessControlList)sd.DiscretionaryAcl;

						//First strip off all existing non-inherited mailbox rights if overwrite was specified
						if(MailboxRightsOverwrite)
						{
							IEnumerator aceEnum = dacl.GetEnumerator();
							while(aceEnum.MoveNext())
							{
								IADsAccessControlEntry currentAce = (IADsAccessControlEntry)aceEnum.Current;
								if((currentAce.AceFlags & (int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERITED_ACE)!=(int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERITED_ACE)
								{
									dacl.RemoveAce(currentAce);
								}
							}
						}
				
						//number of ACEs in the log file
						ACEEntryCount = lstXml[0].ChildNodes[i].ChildNodes[1].ChildNodes.Count;

						//loop through ACEs
						for(int j=0;j<=ACEEntryCount-1;j++)
						{

							IADsAccessControlEntry newAce = new AccessControlEntryClass();

							string Trustee = lstXml[0].ChildNodes[i].ChildNodes[1].ChildNodes[j].Attributes["Trustee"].Value.ToString();
							if(Trustee!=null)
							{

								//ChildNodes[1] denotes the NotInherited node
								string[] PermissionsArray = lstXml[0].ChildNodes[i].ChildNodes[1].ChildNodes[j].Attributes["Mask"].Value.ToString().Split(' ');
								for(int k=0; k<=PermissionsArray.GetUpperBound(0);k++)
								{
									if(PermissionsArray[k]!="")
									{
										string[] SinglePermissionsArray = PermissionsArray[k].Split('|');
										string Permission = SinglePermissionsArray[0];
										bool Deny = false;
										if(SinglePermissionsArray[1]=="Denied")
										{
											Deny = true;
										}
						
										newAce.Trustee = Trustee;
										int PermissionInt = 0;

										switch(Permission)
										{
											case "ACE_MB_FULL_ACCESS":
												PermissionInt = 0x1;
												break;
											case "ACE_MB_ASSOC_EXT_ACCT":
												PermissionInt = 0x4;
												break;
											case "ACE_MB_DELETE_MB_STORAGE":
												PermissionInt = 0x10000;
												break;
											case "ACE_MB_READ_PERMISSIONS":
												PermissionInt = 0x20000;
												break;
											case "ACE_MB_CHANGE_PERMISSION":
												PermissionInt = 0x40000;
												break;
											case "ACE_MB_TAKE_OWNERSHIP":
												PermissionInt = 0x80000;
												break;
										}
		
										newAce.AccessMask = PermissionInt;
										if(!Deny)
										{
											newAce.AceType = (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED;
										}
										else
										{
											newAce.AceType = (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_DENIED;
										}
										newAce.AceFlags = 2;
										dacl.AddAce(newAce);
									}

								
						
								}
							}
					
						}

						sd.DiscretionaryAcl = dacl;
						objUser.MailboxRights = sd;
						ent.CommitChanges();
						log.LogSuccess(logWriter, UserDN, "Import Mailbox Rights", "Not Available When Importing Mailbox Rights", "Mailbox Rights Imported");
						//ent.Dispose();
					}
					catch(System.Exception caught)
					{
						string FailureMessage = "ADMODIFY.ERR - " + caught.Message;
						if(FailureMessage=="ADMODIFY.ERR - Catastrophic failure")
						{
							//we failed most likely because the users mailbox store is inaccessible
							FailureMessage = "ADMODIFY.ERR - A Catastrophic failure has occured.  Please verify that the users mailbox store is online.";
						}
						if(FailureMessage=="ADMODIFY.ERR - Unspecified error")
						{
							//the user most likely doesn't have a mailbox
							FailureMessage = "ADMODIFY.ERR - An Unspecified Error has occured.  Please ensure that the user being modified has an Exchange Mailbox.";				
						}
						log.LogFailure(logWriter, UserDN, "Import Mailbox Rights", FailureMessage);
					}
				
				}




			if(UserCount==CurrentUserCount & dots <51)
			{
				//sometimes the decimal math doesn't leave us with a
				//51st dot so we have to add it ourselves.
				Console.Write(".");
			}

			//show results to the console
			Console.WriteLine("");
			Console.WriteLine("");
			log.showResults();
			logWriter.Flush();
			logWriter.Close();

		}

		
	}

}
